﻿// Copyright (c) 2011 Dan Popick

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace Open.Web.Stijl.Partitioning
{
	/// <summary>
	/// Partial partitioning solution (though solution is complete when Unassigned is empty)
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class PartialSolution<T> where T : PartitionedItem
	{
		static Utility.Tracer<PartialSolution<T>> _log = new Utility.Tracer<PartialSolution<T>>();
		static int _seed = 0;
		static Configuration.StijlConfiguration _config = Configuration.StijlConfiguration.Default;

		/// <summary> Unique ID, for debugging purposes </summary>
		public int UID { get; set; }
		/// <summary> Groups in the solution </summary>
		public List<Set<T>> AssignedGroups { get; set; }
		/// <summary> Items not yet assigned in the solution </summary>
		public List<T> Unassigned { get; set; }
		/// <summary> partial work used to explore solution tree </summary>
		public object Artefacts { get; set; }
		/// <summary> level of the solution, starting from 0 for the first move </summary>
		public int Level { get; set; }

		public PartialSolution()
		{
			UID = System.Threading.Interlocked.Increment(ref _seed);
			AssignedGroups = new List<Set<T>>();
			Unassigned = new List<T>();
		}

		public PartialSolution(PartialSolution<T> partSolution)
		{
			UID = System.Threading.Interlocked.Increment(ref _seed);
			AssignedGroups = partSolution.AssignedGroups.Select(x => new Set<T>(x)).ToList();
			Unassigned = new List<T>(partSolution.Unassigned.ToArray());
			Level = partSolution.Level;
		}

		public int GetTotalArea()
		{
			return AssignedGroups.Sum(x => (x.Size * x.SecondarySize) + _config.TiledImageThreshold); 
		}

		public string Log()
		{
			StringBuilder sb = new StringBuilder();
			sb.AppendFormat("Solution: ({0}, level: {1}) unassigned={2}, groups={3}\r\n",
				UID, Level, Unassigned.Count, AssignedGroups.Count);
			if (Unassigned != null)
				sb.AppendFormat("  unassigned: {0}\r\n",
					String.Join(", ", Unassigned.Select(x => x.Size.ToString()).ToArray()));
			if (AssignedGroups != null)
				foreach (Set<T> set in AssignedGroups)
					sb.AppendFormat("{0}\r\n", set.Log(2));

			return sb.ToString();
		}
	}
}
